package com.anlu.base.reflection;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sound.midi.Soundbank;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectTest {
    private final static Logger logger = LoggerFactory.getLogger(ReflectTest.class);

    public static void main(String[] args) throws Exception {

//        classTest();

//        methodTest();

//        reflectCreateInstance();

//        reflectAccessProperty();
        reflectAccessMethod();
    }


    static void reflectAccessMethod() throws Exception {
        Class<?> userClass = Class.forName("com.anlu.base.model.Person");

        //创建对象
        Object o = userClass.newInstance();

        Method hi = userClass.getMethod("hi",String.class);
        //调用
        hi.invoke(o,"小明");


        //调用private static方法
        Method say = userClass.getDeclaredMethod("say",int.class,String.class,char.class);
        say.setAccessible(true);

        say.invoke(o,1,"张三","男");

        //获取返回值
        Object reVal = say.invoke(null,300,"王五","男");
        System.out.println("运行类型:"+reVal.getClass());

    }

    /**
     * 反射访问类中的成员
     */
    static void reflectAccessProperty() throws Exception{
        Class<?> userClass = Class.forName("com.anlu.base.model.Person");

        //创建对象
        Object o = userClass.newInstance();
        logger.info(o.getClass().toString());

        //使用反射得到age属性对象
        Field age = userClass.getDeclaredField("age");
        age.setAccessible(true);
        //使用反射得到age属性的值
        logger.info((String) age.get(o));

        //通过反射操作属性
        age.set(o,88);

        logger.info(o.toString());

        //通过反射操作name的值
        Field name = userClass.getDeclaredField("name");
        //对name进行爆破
        name.setAccessible(true);
        name.set(o,"小明");
        //获取属性的值
        logger.info(name.get(o).toString());

        logger.info(o.toString());


    }

    /**
     * 利用反射创建对象
     */
    static void reflectCreateInstance() throws Exception {
        Class<?> userClass = Class.forName("com.anlu.base.model.Person");

        //通过public的无参构造器创建实例
        Object user1 = userClass.newInstance();
        logger.info( user1.toString());

        //通过public的有参数构造器创建实例
        Constructor<?> constructor = userClass.getConstructor(String.class);

        //创建实例
        Object user2 = constructor.newInstance("小月心");
        logger.info(user2.toString());

        //通过非public的有参构造器创建实例
        Constructor<?> constructor1 = userClass.getDeclaredConstructor(Integer.class,String.class);

        //暴力破解
        constructor1.setAccessible(true);
        Object user3 = constructor1.newInstance(100,"张三丰");
        logger.info(user3.getClass().getName());


    }

    static void methodTest()throws ClassNotFoundException{
        //得到Class对象
        Class<?> personCls = Class.forName("com.anlu.base.model.Person");

        Field[] declaredFields = personCls.getDeclaredFields();
        for(Field declaredField: declaredFields){
            logger.info("本类中所有的属性:{};该属性的修饰符:{};该属性的类型:{}",declaredField.getName(),declaredField.getModifiers(),declaredField.getType());
        }

        logger.info("=============================");

        //获取所有的方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for(Method declaredMethod: declaredMethods){
            logger.info("本类中所有的方法:{};该方法的修饰符:{};该方法的返回类型:{}",declaredMethod.getName(),declaredMethod.getModifiers(),declaredMethod.getReturnType());
        }

        //输出当前这个方法的形参情况
        for(Method declaredMethod : declaredMethods){
            Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
            for(Class<?> parameterType: parameterTypes){
                logger.info("该方法的形参是:{}",parameterType);
            }
        }

        logger.info("=============================");


        Constructor<?>[] declaredConstractors = personCls.getDeclaredConstructors();
        for(Constructor<?> declaredConstructor:declaredConstractors){
            //本类中所有的构造器
            logger.info("本类中所有的构造器是:{}",declaredConstructor.getName());
        }

        for(Constructor<?> declaredConstructor:declaredConstractors){

            Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
            for(Class<?> parameterType:parameterTypes){
                logger.info("该构造器中形参类型是:{}",parameterType);
            }
            //本类中所有的构造器
        }


    }

    static void classTest() throws ClassNotFoundException {
        //得到class对象

        Class<?> personCls = Class.forName("com.anlu.base.model.Person");

        //getName获取类的全名
        System.out.println(personCls.getName());

        //获取类的简称
        System.out.println(personCls.getSimpleName());

        //getFields:获取所有的public修饰的属性，包含类以及父类
        Field[] fields = personCls.getFields();

        for (Field field : fields){
            System.out.println("本类以及父类的属性="+field.getName());
        }
        //获取本类的所有属性

        Field[] declareFields = personCls.getDeclaredFields();
        for (Field field : declareFields){
            System.out.println("==本类所有以及父类的属性="+field.getName());
        }

        //获取所有的public修饰的方法，包含类以及父类的
        Method[] methods = personCls.getMethods();
        for(Method method : methods){
            System.out.println("本类以及父类的方法="+method.getName());
        }

        //获取本类的所有的方法
        Method[] declareMethods = personCls.getDeclaredMethods();
        for(Method method:declareMethods){
            System.out.println("本类所有以及父类的方法="+method.getName());
        }

        System.out.println("======================");

        //获取所有的public修饰的构造器 包含本类
        Constructor<?>[] constructors = personCls.getConstructors();

        for(Constructor<?> constructor:constructors){
            System.out.println("本类的构造器="+constructor.getName());
        }
        System.out.println("======================");

        Constructor<?>[] declareConstructs = personCls.getDeclaredConstructors();

        for(Constructor<?> constructor:declareConstructs){
            System.out.println("本类的所有构造器="+constructor.getName());
        }
        System.out.println("======================");

        //获取包名信息
        System.out.println(personCls.getPackage());

        Class<?> superclass = personCls.getSuperclass();
        System.out.println("父类的class对象是:"+superclass);

        Class<?>[] interfaces = personCls.getInterfaces();
        for(Class<?> anInterface : interfaces){
            System.out.println("接口信息:"+anInterface);
        }

        System.out.println("======================");

        //获取所有的注解
        Annotation[] annotations = personCls.getAnnotations();
        for(Annotation annotation : annotations){
            System.out.println("注解信息:"+annotation);
        }
    }


}
